home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / emac16as.arc / IBM.ASM < prev    next >
Assembly Source File  |  1990-04-01  |  32KB  |  1,494 lines

  1. ;History:772,1
  2. ;Mon Mar 26 03:22:48 1990 If they enter e0 using the alt-keypad, pretend it's a real key.
  3. ;Sun Mar 25 13:07:39 1990 Forgot to set num_screen_cols in monochrome mode.
  4. ;Sat Feb 24 20:51:15 1990 M-Escape was M-Esc, which was wrong.
  5. ;Thu Jan 11 23:59:48 1990 Only force video mode 3 if there is no memory at b000:0
  6. ;Wed Oct 11 22:43:28 1989 When inversing, swap the colors rather than xoring with 77h.
  7. ;Sun Sep 24 23:18:42 1989 fix the desqview support.
  8. ;Sun Sep 24 23:05:51 1989 reserve a column on the right for the scroll bar.
  9. ;Tue Sep 19 23:01:46 1989 add Desqview support.
  10. ;Thu Jun 15 23:29:25 1989 Didn't restore port 61h correctly -- crashes a PC.
  11. ;Thu Jun 15 00:27:41 1989 clear_count was destroying dx if ibm_cga != 0.
  12. ;Sun May 28 00:52:17 1989 Use a different method of testing for enhanced keyboards.
  13. ;Sun May 07 00:40:17 1989 Move mouse code from pick.asm to ibm.asm
  14. ;Wed May 03 22:15:40 1989 change the arguments to ring_the_bell.
  15. ;Wed May 03 21:10:32 1989 'and' the background color with 7 to avoid blinking.
  16. ;Tue Mar 07 23:57:47 1989 add parameters to ring_the_bell
  17. ;Tue Mar 07 23:46:52 1989 add Jonathan Vail's visual bell code.
  18. ;Tue Feb 21 22:20:40 1989 add keypad key support.
  19. ;Sat Feb 18 16:57:32 1989 Use hardware cursor positioning for EGA only.
  20. ;Fri Feb 17 22:35:11 1989 cleaned up snow-avoidance code a little.
  21. ;Mon Jan 30 22:58:16 1989 change the parameters for set_screen_color.
  22. ;08-25-88 23:37:09 Create two new keycodes, "C- " and "M- ".
  23. ;05-30-88 22:27:44 fix a small problem in save/restore screen
  24. ;05-29-88 22:49:48 try getting the attributes from lower left.
  25. ;05-29-88 22:42:39 get the attributes from the lower right corner rather than upper right.
  26. ;05-27-88 23:25:34 fix a problem in putch where it put garbage characters up.
  27. ;05-27-88 00:09:00 read_ibm_cga sometimes gets called with ds=bufseg, not data.
  28. ;05-27-88 00:07:02 move_line didn't respect ibm_cga flag--it was always set.
  29. ;05-17-88 20:33:20 Add support for hardware scrolls (should work for all displays) [kdb]
  30. ;05-17-88 20:02:45 Make move_line wait while reading cga screen [kdb]
  31. ;05-17-88 19:35:35 Remove all reference to scrwait function [kdb]
  32. ;05-17-88 19:03:22 Macroize scrwait for single char [kdb]
  33. ;05-15-88 19:16:51 add scrwait in scrolls [kdb]
  34. ;05-15-88 18:58:45 Make move_line wait for each character [kdb]
  35. ;05-07-88 22:07:59 implement a swap_screen_flag.
  36. ;05-03-88 23:54:55 add more extended keys.
  37. ;04-17-88 19:22:28 add some extended keycodes.
  38. ;04-16-88 13:13:01 add extended keyboard support.
  39. ;04-14-88 22:51:58 If ibm_cga, don't store_debug.
  40. ;04-01-88 23:08:28 respond to mouse keys with M-, S-, and C-
  41. ;03-31-88 22:02:25 use C-break for the break character (duh)
  42. ;03-28-88 19:19:14 just clear the screen on a MDA.
  43. ;03-28-88 19:09:19 don't save and restore video memory on an MDA.
  44. ;03-28-88 18:28:50 remove block_cursor and under_cursor
  45. ;03-26-88 21:59:07 change back to bios calls to read the keyboard.
  46. ;03-24-88 00:02:13 add fore_original and back_original.
  47. ;02-21-88 12:24:50 make control be bright, meta inverse video.
  48. ;02-13-88 18:22:56 use the 18.2 ms timer tick to time the beep.
  49. ;02-13-88 16:43:45 don't map Timeout using M-, C-, or S-
  50. ;12-07-87 20:07:29 add store_debug
  51. ;12-05-87 11:23:35 make the color default to the current color.
  52. ;12-05-87 11:20:13 clear the screen on init_entry.
  53. ;12-05-87 11:16:53 save dos's screen and restore it when finished.
  54. ;07-05-87 22:14:22 caps lock shouldn't apply to M- and C- keys.
  55.     page    ,132
  56.  
  57. comment /
  58.  
  59.     Porting EMACS and Percival to MS-DOS computers other than the Z-100:
  60.  
  61. This entire file (Z-100.ASM) needs to be re-written, since it contains
  62. all the Z-100 dependencies.  The following conventions must be maintained:
  63.   1) Never leave this module with DF=1.
  64.   2) Never destroy ES.
  65.   3) Never MOV AX,DATA, always use the copy in the appropriate segment register.
  66.   4) Return NC if a routine succeeds, or fulfills its goals.
  67.  
  68. /
  69.     .xlist
  70.     include    memory.def
  71.  
  72.  
  73. data    segment    byte public
  74.  
  75.     public    max_screen_line
  76. max_screen_line    db    22    ;number of last text row on screen.
  77.  
  78.     public    num_screen_cols
  79. num_screen_cols    db    ?
  80.     db    0            ;in case they access it as a word.
  81.  
  82. screen_columns    db    ?
  83.     db    0            ;in case they access it as a word.
  84.  
  85.     public    fore_original, back_original
  86. fore_original    db    ?
  87. back_original    db    ?
  88.  
  89.  
  90.     public    scan_lines_per_char
  91. scan_lines_per_char    db    8
  92.  
  93.     public    computer_name, computer_name_len
  94. computer_name    db    'IBM-PC'
  95. computer_name_len    equ    $-computer_name
  96.  
  97.     public    swap_screen_flag
  98. swap_screen_flag    dw    1    ;=1 if we should swap screens.
  99.  
  100. old_cursor    dw    ?        ;old cursor position from the swapped
  101.                     ;  screen.
  102.  
  103. mouse_flag    db    ?
  104. mouse_buttons    db    ?
  105.  
  106.  
  107. key_names    label    byte
  108.     db    ',','Comma',0
  109.     db    '(','LPar',0
  110.     db    ')','RPar',0
  111.     db    7fh,'Delete',0
  112.  
  113.     db    -1,'Timeout',0
  114.     db    -2,'Left Down',0        ;mouse button key names.
  115.     db    -3,'Right Down',0
  116.     db    -4,'Left Up',0
  117.     db    -5,'Right Up',0
  118.     db    -6,'Middle Down',0
  119.     db    -7,'Middle Up',0
  120.     db    0
  121.  
  122.  
  123. key_others    label    byte
  124.     db    14,'Back Space',0
  125.     db    15,'Tab',0
  126.     db    28,'Return',0
  127.     db    1,'Escape',0
  128.  
  129.     db    71,'KP7',0        ;Home
  130.     db    72,'KP8',0        ;UpArrow
  131.     db    73,'KP9',0        ;PgUp
  132.     db    74,'KP-',0        ;MMinus
  133.     db    75,'KP4',0        ;LeftArrow
  134.     db    76,'KP5',0        ;Five
  135.     db    77,'KP6',0        ;RightArrow
  136.     db    78,'KP+',0        ;MPlus
  137.     db    79,'KP1',0        ;End
  138.     db    80,'KP2',0        ;DownArrow
  139.     db    81,'KP3',0        ;PgDn
  140.     db    82,'KP0',0        ;Ins
  141.     db    83,'KP.',0        ;Del
  142.  
  143.     db    0
  144.  
  145.  
  146. key_special    label    byte
  147.     db    127,'C-Back Space',0
  148.     db    10,'C-Return',0
  149.     db    0
  150.  
  151. key_table    label    byte
  152. ;    db    0,'000',0
  153.     db    1,'M-Escape',0        ;extended
  154. ;    db    2,'002',0
  155.     db    3,'C-@',0
  156. ;    db    4,'004',0
  157. ;    db    5,'005',0
  158. ;    db    6,'006',0
  159. ;    db    7,'007',0
  160. ;    db    8,'008',0
  161. ;    db    9,'009',0
  162. ;    db    10,'010',0
  163. ;    db    11,'011',0
  164. ;    db    12,'012',0
  165. ;    db    13,'013',0
  166.     db    14,'M-Back Space',0    ;extended
  167.     db    15,'S-Tab',0
  168.     db    16,'M-q',0
  169.     db    17,'M-w',0
  170.     db    18,'M-e',0
  171.     db    19,'M-r',0
  172.     db    20,'M-t',0
  173.     db    21,'M-y',0
  174.     db    22,'M-u',0
  175.     db    23,'M-i',0
  176.     db    24,'M-o',0
  177.     db    25,'M-p',0
  178.     db    26,'M-{',0        ;extended
  179.     db    27,'M-}',0        ;extended
  180.     db    28,'M-Return',0        ;extended
  181. ;    db    29,'029',0
  182.     db    30,'M-a',0
  183.     db    31,'M-s',0
  184.     db    32,'M-d',0
  185.     db    33,'M-f',0
  186.     db    34,'M-g',0
  187.     db    35,'M-h',0
  188.     db    36,'M-j',0
  189.     db    37,'M-k',0
  190.     db    38,'M-l',0
  191.     db    39,'M-;',0        ;extended
  192.     db    40,"M-'",0        ;extended
  193.     db    41,'M-`',0        ;extended
  194. ;    db    42,'042',0
  195.     db    43,'M-\',0        ;extended
  196.     db    44,'M-z',0
  197.     db    45,'M-x',0
  198.     db    46,'M-c',0
  199.     db    47,'M-v',0
  200.     db    48,'M-b',0
  201.     db    49,'M-n',0
  202.     db    50,'M-m',0
  203.     db    51,'M-Comma',0        ;extended
  204.     db    52,'M-.',0        ;extended
  205.     db    53,'M-/',0        ;extended
  206. ;    db    54,'054',0
  207.     db    55,'M-Asterisk',0
  208. ;    db    56,'056',0
  209. ;    db    57,'057',0
  210. ;    db    58,'058',0
  211.     db    59,'F1',0
  212.     db    60,'F2',0
  213.     db    61,'F3',0
  214.     db    62,'F4',0
  215.     db    63,'F5',0
  216.     db    64,'F6',0
  217.     db    65,'F7',0
  218.     db    66,'F8',0
  219.     db    67,'F9',0
  220.     db    68,'F10',0
  221. ;    db    69,'069',0
  222. ;    db    70,'070',0
  223.     db    71,'Home',0
  224.     db    72,'Up Arrow',0
  225.     db    73,'Pg Up',0
  226.     db    74,'M-Minus',0
  227.     db    75,'Left Arrow',0
  228.     db    76,'Five',0
  229.     db    77,'Right Arrow',0
  230.     db    78,'M-Plus',0
  231.     db    79,'End',0
  232.     db    80,'Down Arrow',0
  233.     db    81,'Pg Dn',0
  234.     db    82,'Ins',0
  235.     db    83,'Del',0
  236.     db    84,'S-F1',0
  237.     db    85,'S-F2',0
  238.     db    86,'S-F3',0
  239.     db    87,'S-F4',0
  240.     db    88,'S-F5',0
  241.     db    89,'S-F6',0
  242.     db    90,'S-F7',0
  243.     db    91,'S-F8',0
  244.     db    92,'S-F9',0
  245.     db    93,'S-F10',0
  246.     db    94,'C-F1',0
  247.     db    95,'C-F2',0
  248.     db    96,'C-F3',0
  249.     db    97,'C-F4',0
  250.     db    98,'C-F5',0
  251.     db    99,'C-F6',0
  252.     db    100,'C-F7',0
  253.     db    101,'C-F8',0
  254.     db    102,'C-F9',0
  255.     db    103,'C-F10',0
  256.     db    104,'M-F1',0
  257.     db    105,'M-F2',0
  258.     db    106,'M-F3',0
  259.     db    107,'M-F4',0
  260.     db    108,'M-F5',0
  261.     db    109,'M-F6',0
  262.     db    110,'M-F7',0
  263.     db    111,'M-F8',0
  264.     db    112,'M-F9',0
  265.     db    113,'M-F10',0
  266.     db    114,'C-PrtSc',0
  267.     db    115,'C-Left Arrow',0
  268.     db    116,'C-Right Arrow',0
  269.     db    117,'C-End',0
  270.     db    118,'C-Pg Dn',0
  271.     db    119,'C-Home',0
  272.     db    120,'M-1',0
  273.     db    121,'M-2',0
  274.     db    122,'M-3',0
  275.     db    123,'M-4',0
  276.     db    124,'M-5',0
  277.     db    125,'M-6',0
  278.     db    126,'M-7',0
  279.     db    127,'M-8',0
  280.     db    128,'M-9',0
  281.     db    129,'M-0',0
  282.     db    130,'M--',0
  283.     db    131,'M-=',0
  284.     db    132,'C-Pg Up',0
  285. ;all of the following are extended.
  286.     db    133,'F11',0
  287.     db    134,'F12',0
  288.     db    135,'S-F11',0
  289.     db    136,'S-F12',0
  290.     db    137,'C-F11',0
  291.     db    138,'C-F12',0
  292.     db    139,'M-F11',0
  293.     db    140,'M-F12',0
  294.     db    141,'C-Up Arrow',0
  295.     db    142,'C-Minus',0
  296.     db    143,'C-Five',0
  297.     db    144,'C-Plus',0
  298.     db    145,'C-Down Arrow',0
  299.     db    146,'C-Ins',0
  300.     db    147,'C-Del',0
  301.     db    148,'C-Tab',0
  302.     db    149,'C-Slash',0
  303.     db    150,'C-Asterisk',0
  304.     db    151,'M-Home',0
  305.     db    152,'M-Up Arrow',0
  306.     db    153,'M-Pg Up',0
  307. ;    db    154,'154',0
  308.     db    155,'M-Left Arrow',0
  309. ;    db    156,'156',0
  310.     db    157,'M-Right Arrow',0
  311. ;    db    158,'158',0
  312.     db    159,'M-End',0
  313.     db    160,'M-Down Arrow',0
  314.     db    161,'M-Pg Dn',0
  315.     db    162,'M-Ins',0
  316.     db    163,'M-Del',0
  317.     db    164,'M-Slash',0
  318.     db    165,'M-Tab',0
  319.     db    166,'M-Return',0
  320.     db    167,'C- ',0
  321.     db    168,'M- ',0
  322.  
  323. ;    db    224,'Slash',0
  324. ;    db    224,'Return',0
  325.  
  326.     db    0,'Unknown',0
  327.  
  328.  
  329. one_key_string    db    ?,0
  330. ctrl_key_string    db    'C-'
  331. ctrl_key_char    db    ?,0
  332.  
  333. left_flag    equ    1
  334. right_flag    equ    2
  335. ctrl_flag    equ    4
  336. alt_flag    equ    8
  337. all_flags    equ    left_flag + right_flag + ctrl_flag + alt_flag
  338. shift_flags    db    ?
  339.  
  340. bios_seg    segment at 40h
  341.     org    17h
  342. bios_shifts    db    ?
  343. bios_seg    ends
  344.  
  345.  
  346. key_buffer    label    byte        ;this is where we put the ASCII
  347.     db    26 dup(?)        ;  representation of the key.
  348.  
  349.  
  350.     extrn    inversing: word        ;if we're inverse videoing.
  351.  
  352.     public    color
  353. color        db    0fh        ;xbbbifff bbb=background, ifff=fore.
  354. control_color    db    1fh        ;attributes for control characters.
  355. whitespc_color    db    0fh        ;attributes for whitespace characters.
  356.  
  357. font_8_table    label    byte
  358.     db    007h            ;visi space
  359.     db    004h            ;visi tab
  360.     db    ?            ;del
  361.     db    ?            ;eof
  362.     db    ?            ;visi newline
  363.     db    01ah            ;right arrow
  364.     db    ?            ;random char.
  365.     db    01fh            ;visible newline.
  366.     db    018h            ;up arrow.
  367.     db    019h            ;down arrow.
  368.     db    20h            ;trailing space
  369.  
  370. ibm_cga    db    0            ;=0 if we can write to screen anytime,
  371.                     ;=1 if we should wait for retrace.
  372. have_ega    db    0        ;=0 if we don't have an EGA.
  373.  
  374. int_16_input    db    0        ;function code for keyboard input
  375. int_16_status    db    1        ;function code for keyboard status
  376.  
  377. in_dv        db    0        ;<>0 if we are running under DesqView.
  378.  
  379. data    ends
  380.  
  381.  
  382. code    segment    byte public
  383.     assume    cs:code, ds:data, es:nothing
  384. ;all of the code in this segment is called with the above assumes.
  385.  
  386. break_flag    db    ?
  387.  
  388. their_1b    dd    ?
  389. our_1b:
  390.     mov    cs:break_flag,1
  391.     iret
  392.  
  393.  
  394.     public    init_entry
  395. init_entry:
  396.     push    es            ;get their C-break.
  397.     mov    ax,351bh
  398.     int    21h
  399.     mov    word ptr their_1b+0,bx
  400.     mov    word ptr their_1b+2,es
  401.     pop    es
  402.  
  403.     push    ds            ;set our C-break.
  404.     mov    ax,cs
  405.     mov    ds,ax
  406.     mov    dx,offset our_1b
  407.     mov    ax,251bh
  408.     int    21h
  409.     pop    ds
  410.  
  411. ;
  412. ;Determine if Desqview is present.
  413. ;
  414.     mov    cx,'DE'
  415.     mov    dx,'SQ'
  416.     mov    ax,2b01h
  417.     int    21h
  418.     cmp    al,0ffh
  419.     je    no_desqview
  420.     inc    in_dv
  421. no_desqview:
  422.  
  423. ;
  424. ;Determine whether or not the BIOS supports extended keyboard functions.
  425. ;
  426.     push    ds
  427.     mov    ax,40h
  428.     mov    ds,ax
  429.     mov    al,ds:[96h]        ;keyboard support byte.
  430.     pop    ds
  431.     test    al,10h
  432.     je    init_entry_0        ;no - they don't have an extended kbd.
  433.  
  434.     mov    int_16_input,10h    ;yes - use extended keyboard function codes.
  435.     mov    int_16_status,11h
  436. init_entry_0:
  437.  
  438. ;
  439. ;Now set the video mode to one that we can use.
  440. ;
  441.     mov    ah,15
  442.     int    10h            ;get video state of the PC
  443.     mov    screen_columns,40
  444.     mov    num_screen_cols,40
  445.     cmp    al,1            ;40 column text mode?
  446.     jbe    init_entry_1        ;Yes, ok.
  447.     mov    screen_columns,80
  448.     mov    num_screen_cols,80
  449.     cmp    al,3            ;Is screen CGA Text?
  450.     jbe    init_entry_1        ;Yes, ok.
  451.     cmp    al,7            ;Is screen MDA?
  452.     je    init_entry_5        ;Yes, ok - but we can't have an EGA.
  453.  
  454. ;
  455. ;Check to make sure there's memory at b800h.  If there isn't, revert to
  456. ;video mode 3.
  457. ;
  458.     push    ds
  459.     mov    ax,0b800h
  460.     mov    ds,ax
  461.     mov    ax,ds:[0]        ;save the original
  462.     not    word ptr ds:[0]        ;try to change the memory.
  463.     not    ax            ;change the original.
  464.     cmp    ax,ds:[0]        ;did they both change?
  465.     pushf
  466.     not    ax            ;restore the original contents.
  467.     mov    ds:[0],ax
  468.     popf
  469.     pop    ds
  470.     je    init_entry_1        ;go if there's memory there.
  471.  
  472.     mov    ax,0*256 + 3        ;use 25x80 color if some strange mode.
  473.     int    10h
  474.  
  475. init_entry_1:
  476.     mov    ax,1200h        ;test for an EGA
  477.     mov    bx,10h
  478.     mov    cx,-1
  479.     int    10h
  480.     cmp    cx,-1
  481.     je    init_entry_2        ;no EGA.
  482.  
  483.     mov    have_ega,1        ;remember that we have an EGA.
  484.  
  485.     push    ds            ;get the max scanlines.
  486.     xor    ax,ax
  487.     mov    ds,ax
  488.     mov    al,ds:[484h]
  489.     mov    ah,ds:[485h]
  490.     mov    cl,ds:[44ah]
  491.     pop    ds
  492.  
  493.     mov    screen_columns,cl    ;remember how wide it is.
  494.     sub    al,2            ;leave room for a status and minibuffer line.
  495.     mov    max_screen_line,al
  496.  
  497. init_entry_2:
  498.     mov    al,screen_columns
  499.     mov    num_screen_cols,al
  500.  
  501.     cmp    swap_screen_flag,0    ;should we swap the screen?
  502.     je    init_entry_4        ;no.
  503.  
  504.     mov    bh,0
  505.     mov    ah,3            ;get cursor position
  506.     int    10h
  507.     mov    old_cursor,dx
  508.  
  509.     mov    dl,max_screen_line    ;copy the page zero to page one.
  510.     add    dl,2
  511.     mov    al,dl
  512.     inc    al
  513.     add    al,dl
  514. init_entry_3:
  515.     call    move_line        ;enter with dl=source, al=destination.
  516.     dec    al
  517.     dec    dl
  518.     jns    init_entry_3
  519.  
  520. init_entry_5:
  521.     push    es
  522.     mov    dh,0
  523.     mov    dl,max_screen_line
  524.     add    dl,2
  525.     call    get_video_ptr
  526.     mov    ax,es:[di]        ;get the attributes from the lower left.
  527.     pop    es
  528.     mov    fore_original,ah
  529.     and    fore_original,0fh
  530.     mov    cl,4            ;rotate the background to where we
  531.     shr    ah,cl            ;  want it.
  532.     and    ah,7
  533.     mov    back_original,ah
  534.  
  535. clear_screen:
  536.     mov    dh,0            ;clear the screen.
  537.     mov    dl,max_screen_line
  538.     add    dl,2
  539. clear_screen_1:
  540.     call    clear_to_eol        ;enter with dl=row, dh=column.
  541.     dec    dl
  542.     jns    clear_screen_1
  543. init_entry_4:
  544.     dec    num_screen_cols
  545.     ret
  546.  
  547.  
  548.     public    uninit_exit
  549. uninit_exit:
  550. ;called when exiting.  May destroy any but seg-regs.
  551.  
  552.     push    ds            ;restore C-break.
  553.     lds    dx,their_1b
  554.     mov    ax,251bh
  555.     int    21h
  556.     pop    ds
  557.  
  558.     cmp    swap_screen_flag,0    ;should we swap the screen?
  559.     jne    uninit_exit_4        ;yes.
  560.     ret                ;no.
  561. uninit_exit_4:
  562.  
  563.     inc    num_screen_cols
  564.  
  565.     mov    ah,15
  566.     int    10h            ;get video state of the PC
  567.     cmp    al,7            ;don't restore the memory on an MDA
  568.     je    uninit_exit_1        ;  'cuz it ain't there.
  569.  
  570.     mov    dx,old_cursor
  571.     mov    bh,0
  572.     mov    ah,2            ;set cursor position
  573.     int    10h
  574.  
  575.     mov    al,max_screen_line    ;copy the page one to page zero.
  576.     add    al,2
  577.     mov    dl,al
  578.     add    dl,dl
  579. uninit_exit_3:
  580.     call    move_line        ;enter with dl=source, al=destination.
  581.     dec    dl
  582.     dec    al
  583.     jns    uninit_exit_3
  584.  
  585.     dec    num_screen_cols
  586.  
  587.     ret
  588.  
  589. uninit_exit_1:
  590.     mov    dl,0
  591.     mov    dh,max_screen_line
  592.     add    dh,2
  593.     mov    bh,0
  594.     mov    ah,2            ;set cursor position
  595.     int    10h
  596.  
  597.     call    clear_screen
  598.  
  599.     dec    num_screen_cols
  600.  
  601.     ret
  602.  
  603.  
  604. outreg    macro    port,value
  605.     mov    al,port
  606.     out    dx,al
  607.     inc    dx
  608.     mov    al,value
  609.     out    dx,al
  610.     dec    dx
  611.     endm
  612.  
  613.  
  614.   if 0
  615. set_start_addr:
  616. ;given screen_start (the first text line on the screen), scan_row (the first
  617. ;  scan row we're displaying), and bot_window, set the appropriate registers.
  618.  
  619.     mov    dx,03dah        ;wait for vertical retrace.
  620.     cli                ;no interrupts.
  621. set_start_addr_h:
  622.     in    al,dx            ;Wait for horizontal retrace
  623.     test    al,8            ; so will catch vertical
  624.     jz    set_start_addr_h    ; retrace at start.
  625. set_start_addr_v:
  626.     in    al,dx            ;Wait for vertical retrace.
  627.     rcr    al,1
  628.     jc    set_start_addr_v
  629.  
  630.     mov    dx,03d4h
  631.  
  632.     mov    bx,screen_start        ;screen_start is given in terms of
  633.     shr    bx,1            ;  bytes, but we need words.
  634.     outreg    0ch,bh            ;the high byte of the starting address.
  635.     outreg    0dh,bl            ;the low byte of the starting address.
  636.  
  637.     outreg    08h,scan_row        ;Preset row scan.
  638.  
  639.     mov    bx,bot_window
  640.     shl    bh,1            ;put the bit in the right place.
  641.     shl    bh,1
  642.     shl    bh,1
  643.     shl    bh,1
  644.     or    bh,0fh            ;assume that the rest are ones.
  645.  
  646.     outreg    18h,bl            ;set the low byte of line compare.
  647.     outreg    07h,bh            ;set the overflow bits.
  648.  
  649.     sti
  650.  
  651.     ret
  652.   endif
  653.  
  654.  
  655.     public    store_ibm_cga
  656. store_ibm_cga:
  657.     cmp    have_ega,0        ;do we have an EGA?
  658.     jne    store_ibm_cga_1        ;yes - we know better than they do,
  659.     mov    ibm_cga,al        ;  so ignore them.
  660. store_ibm_cga_1:
  661.     ret
  662.  
  663.  
  664.     public    store_debug
  665. store_debug:
  666.   if 0
  667.     cmp    ibm_cga,0        ;don't do this on an IBM CGA.
  668.     jne    store_debug_1
  669.     push    ds
  670.     push    es
  671.     push    ax
  672.     mov    ax,data
  673.     mov    ds,ax
  674.     mov    es,ax
  675.     mov    dh,screen_columns
  676.     sub    dh,2
  677.     mov    dl,max_screen_line
  678.     inc    dl
  679.     call    get_video_ptr    ;enter with dl=current row, dh=current column.
  680.                 ;return with es:di->character position.
  681.     pop    ax
  682.     mov    es:[di],al
  683.     mov    es:[di+2],ah
  684.     pop    es
  685.     pop    ds
  686. store_debug_1:
  687.   endif
  688.     ret
  689.  
  690.  
  691. ;this routine should check for a break character.  Return cy if none,
  692. ;  nc if we should break.
  693.     public    check_breakchar
  694. check_breakchar:
  695.     cmp    cs:break_flag,0        ;test the break flag.
  696.     mov    cs:break_flag,0        ;clear the break flag.
  697.     stc
  698.     je    check_breakchar_1
  699.     clc
  700. check_breakchar_1:
  701.     ret
  702.  
  703.  
  704.     public    give_up_slice
  705. give_up_slice:
  706.     cmp    in_dv,0
  707.     je    give_up_slice_1
  708.     push    bx
  709.     push    si
  710.     push    bp
  711.     mov    bx,1000h
  712.     int    15h
  713.     pop    bp
  714.     pop    si
  715.     pop    bx
  716. give_up_slice_1:
  717.     ret
  718.  
  719.  
  720.     public    check_for_key
  721. check_for_key:
  722. ;return zr,ax=0 if no key is waiting.
  723. ;return nz,ax=key if a key is waiting, but don't input the key yet.
  724.     mov    ah,int_16_status    ;check for a key.
  725.     int    16h
  726.     jne    check_for_key_1        ;go if we got a key.
  727.     mov    ax,0            ;return ax=0 if we didn't.
  728. check_for_key_1:
  729.     ret
  730.  
  731.  
  732.     public    get_key_value
  733. get_key_value:
  734. ;exit with ax=keycode.
  735.     mov    ah,int_16_input
  736.     int    16h
  737.     ret
  738.  
  739.  
  740.     public    decode_key
  741. decode_key:
  742. ;enter with ax=key value.
  743. ;exit with si,cx -> the key's name in ASCII.
  744.     mov    di,offset key_buffer
  745.  
  746.     cmp    ax,0f9h            ;one of the mouse buttons?
  747.     jb    decode_key_7
  748.     cmp    ax,0feh
  749.     ja    decode_key_7
  750.  
  751.     push    ax
  752.     push    ds
  753.     mov    ax,bios_seg
  754.     mov    ds,ax
  755.     assume    ds:bios_seg
  756.  
  757.     mov    ah,bios_shifts
  758.     and    ah,all_flags        ;isolate the flags we're interested in.
  759.     pop    ds
  760.     assume    ds:data
  761.     mov    shift_flags,ah
  762.     call    decode_meta
  763.     call    decode_ctrl
  764.     call    decode_shift
  765.     pop    ax
  766.  
  767. decode_key_7:
  768.  
  769.     or    al,al            ;extended function key?
  770.     je    decode_key_5
  771.     cmp    ax,00e0h        ;Did they enter e0 using the keypad?
  772.     je    decode_key_6        ;yes -- it's a real key.
  773.     cmp    al,0e0h
  774.     je    decode_key_5
  775.  
  776.     push    ax            ;now we look for ASCII keys that
  777.     mov    si,offset key_others    ;  have dedicated keys.
  778.     call    decode_search        ;search for the scan code names.
  779.     pop    ax
  780.     jne    decode_key_2        ;go if we found it.
  781.  
  782.     mov    ah,al
  783.     mov    si,offset key_names    ;now search for the ASCII keys that
  784.                     ;  we don't (or can't) represent.
  785.     call    decode_search        ;search for the literal names.
  786.     jne    decode_key_1        ;copy it in.
  787.     mov    al,ah
  788.  
  789.     cmp    al,' '            ;control char?
  790.     jae    decode_key_6        ;no
  791.     add    al,'`'            ;yes - convert into letter.
  792.     mov    ctrl_key_char,al
  793.     mov    si,offset ctrl_key_string
  794.     cmp    al,'z'            ;control character > 'C-z'?
  795.     jbe    decode_key_1        ;no.
  796.     sub    ctrl_key_char,'`'-'@'    ;yes - make it C-[, not C-{
  797.     jmp    short decode_key_1
  798. decode_key_2:
  799.     push    si
  800.     mov    si,offset key_special
  801.     mov    ah,al            ;now see if it's one of the ones we
  802.     call    decode_search        ;  know are special.
  803.     pop    ax
  804.     jne    decode_key_1        ;yes - it is.
  805.     mov    si,ax
  806.     jmp    short decode_key_1
  807. decode_key_6:
  808.     mov    one_key_string,al
  809.     mov    si,offset one_key_string
  810.     jmp    short decode_key_1
  811.  
  812. decode_key_5:
  813.     mov    si,offset key_table    ;search for the extended functions.
  814.     call    decode_search
  815. decode_key_1:
  816.     lodsb                ;copy to the next null.
  817.     stosb
  818.     or    al,al
  819.     jne    decode_key_1
  820.     dec    di            ;don't include the null.
  821.     mov    si,offset key_buffer
  822.     mov    cx,di
  823.     sub    cx,si
  824.     ret
  825.  
  826.  
  827. decode_ctrl:
  828.     test    shift_flags,ctrl_flag
  829.     je    decode_ctrl_1
  830.     mov    ax,'C' + '-'*256
  831.     stosw
  832. decode_ctrl_1:
  833.     ret
  834.  
  835.  
  836. decode_shift:
  837.     test    shift_flags,left_flag + right_flag
  838.     je    decode_shift_1
  839.     mov    ax,'S' + '-'*256
  840.     stosw
  841. decode_shift_1:
  842.     ret
  843.  
  844. decode_meta:
  845.     test    shift_flags,alt_flag
  846.     je    decode_meta_1
  847.     mov    ax,'M' + '-'*256
  848.     stosw
  849. decode_meta_1:
  850.     ret
  851.  
  852.  
  853. decode_search:
  854. ;enter with ah=key to search for, si->table.
  855. ;exit with al=key, nz if found, al=0, zr if not found.
  856.     lodsb
  857.     or    al,al            ;end of table?
  858.     je    decode_search_2        ;yes - try shifted values.
  859.     cmp    al,ah            ;is this the key?
  860.     je    decode_search_2        ;yes.
  861. decode_search_1:
  862.     lodsb                ;skip to the next null.
  863.     or    al,al
  864.     jne    decode_search_1
  865.     jmp    decode_search
  866. decode_search_2:
  867.     or    al,al
  868.     ret
  869.  
  870.  
  871.     public    ring_the_bell
  872. ring_the_bell:
  873. ;enter with bx = first argument, cx = second argument.
  874.     or    cx,cx
  875.     jne    ring_the_bell_1
  876.     mov    cx,1            ;defaults to duration of one.
  877. ring_the_bell_1:
  878.     or    bx,bx            ;negative frequency?
  879.     jl    vbell            ;yes - they must want a visual bell.
  880.  
  881.  
  882. ;Beep procedure count values
  883. ;---------------------------
  884. ;To generate a given freqency note out of the speaker with the Beep procedure
  885. ;on the PC using Channel 2 of the 8253 timer, the channel 2 count register
  886. ;must be loaded with a value such that the 8253 input clock frequency
  887. ;(1.19318 MHz) divided by the count figure equals the audio frequency.
  888. ;enter with bx=count figure for frequency to be generated.
  889. beep:
  890.     push    cx
  891.     mov    cx,1
  892.     call    sleep
  893.     pop    cx
  894.     mov    al,0b6h        ; Channel 2, LSB then MSB, Square Wave, Binary
  895.     out    43h,al        ; Program 8253 command register
  896.     mov    ax,bx        ; Get the frequency to be generated
  897.     out    42h,al        ; Load Channel 2 count register LSB
  898.     mov    al,ah
  899.     out    42h,al        ; Load Channel 2 count register MSB
  900.     in    al,61h        ; Read settings from 8255 PPI I/O Port "PB"
  901.     push    ax        ; Save original settings in AH
  902.     or    al,3        ; Enable Timer Channel 2 & Speaker data
  903.     out    61h,al        ; program the 8255 with new setting-speaker on
  904.     call    sleep        ; Wait for a while.
  905.     pop    ax        ; Get original 8255 Port "PB" settings
  906.     out    61h,al        ; Reset port to original values-speaker off
  907.     ret
  908.  
  909.  
  910. vbell:
  911.     push    cx
  912.     mov    cx,1            ;get syncronized with the timer
  913.     call    sleep
  914.  
  915.     call    reverse
  916.  
  917.     pop    cx            ;now wait that many seconds.
  918.     or    cx,cx            ;if zero duration, just wait one tick.
  919.     jne    vbell_1
  920.     mov    cx,1
  921. vbell_1:
  922.     call    sleep
  923.  
  924. reverse:
  925.     push    di            ; Save es,di
  926.     push    es
  927.     call    get_video_seg
  928.  
  929.     mov    ah,num_screen_cols    ; Calc number of chars
  930.     mov    al,max_screen_line
  931.     add    al,2            ; the entire screen
  932.     mul    ah
  933.     mov    cx,ax
  934.     mov    di,1            ; Offset to start at
  935. rev1:
  936.     mov    al,es:[di]    ; Reverse the foreground/background
  937.     rol    al,1
  938.     rol    al,1
  939.     rol    al,1
  940.     rol    al,1
  941.     and    al,77h
  942.     and    byte ptr es:[di],not 77h
  943.     or    es:[di],al
  944.     add    di,2
  945.     loop    rev1
  946.  
  947.     pop    es
  948.     pop    di
  949.  
  950.     ret
  951.  
  952.  
  953. sleep:
  954. ;pause for cx 18ths.
  955.     push    bx
  956.     push    ds        ; make ds = bios.
  957.     mov    ax,40h
  958.     mov    ds,ax
  959. wait2:
  960.     mov    bx,ds:[6ch]    ; Get the current timer value.
  961. wait1:
  962.     cmp    bx,ds:[6ch]    ; Did the timer value "tick"?
  963.     je    wait1        ; No - keep waiting for a tick.
  964.     loop    wait2        ; LOOP is first executed
  965.     pop    ds
  966.     pop    bx
  967.     ret
  968.  
  969.  
  970. code    ends
  971.  
  972. code    segment    byte public
  973.     assume    cs:code, ds:nothing, es:data, ss:data
  974. ;all of the code in this segment is called with the above assumes.
  975.  
  976.  
  977.     public    read_ibm_cga
  978. read_ibm_cga:
  979.     mov    al,ibm_cga
  980.     ret
  981.  
  982.  
  983.     public    position_cursor
  984. position_cursor:
  985. ;enter with dh=col (0...80), dl=row (0..max_screen_line)
  986. ;exit with cursor set to that position.
  987.     push    bx
  988.     push    dx
  989.     push    si
  990.     push    di
  991.     push    bp
  992.  
  993.     xchg    dh,dl
  994.     mov    bh,0
  995.     mov    ah,2            ;set cursor position
  996.     int    10h
  997.  
  998.     pop    bp
  999.     pop    di
  1000.     pop    si
  1001.     pop    dx
  1002.     pop    bx
  1003.     ret
  1004.  
  1005.  
  1006. crt_status equ  3dah                    ; crt status port
  1007.  
  1008. ;requires dx = crt_status.  Destroys ax.
  1009. retrace_wait    macro
  1010.     local    loop1,loop2
  1011. loop1:
  1012.     in    al,dx
  1013.     shr    al,1            ; display enabled?
  1014.     jc    loop1            ; yes, keep waiting
  1015. loop2:
  1016.     in    al,dx
  1017.     shr    al,1            ; now wait for it to go    off
  1018.     jnc    loop2            ; so can have whole cycle
  1019.     endm
  1020.  
  1021.  
  1022.     public    move_line
  1023. move_line:
  1024. ;enter with dl=source row, al=destination row.
  1025.     push    ax
  1026.     push    bx
  1027.     push    cx
  1028.     push    dx
  1029.     push    si
  1030.     push    di
  1031.     push    bp
  1032.     push    ds
  1033.     push    es
  1034.  
  1035.     push    ax            ;compute the source byte.
  1036.     mov    al,screen_columns
  1037.     mul    dl
  1038.     shl    ax,1
  1039.     mov    si,ax
  1040.     pop    ax
  1041.  
  1042.     mov    ah,screen_columns    ;compute the destination byte.
  1043.     mul    ah
  1044.     shl    ax,1
  1045.     mov    di,ax
  1046.  
  1047.     mov    cx,word ptr num_screen_cols    ;move the line.
  1048.     call    get_video_seg        ;get the video card plane.
  1049.     mov    ds,ax
  1050.     assume    ds:nothing, es:nothing
  1051.  
  1052.     cmp    ibm_cga,0
  1053.     je    move_line_2
  1054.  
  1055.     mov    dx,crt_status        ;load it only once.
  1056. move_line_1:
  1057.     retrace_wait
  1058.     lodsw                ;get our char into bx.
  1059.     mov    bx,ax
  1060.     retrace_wait
  1061.     mov    ax,bx
  1062.     stosw
  1063.     loop    move_line_1
  1064.     jmp    short move_line_3
  1065.  
  1066. move_line_2:
  1067.     rep    movsw
  1068.  
  1069. move_line_3:
  1070.  
  1071.     pop    es
  1072.     pop    ds
  1073.     assume    ds:nothing, es:data
  1074.     pop    bp
  1075.     pop    di
  1076.     pop    si
  1077.     pop    dx
  1078.     pop    cx
  1079.     pop    bx
  1080.     pop    ax
  1081.     ret
  1082.  
  1083.  
  1084.     public    clear_to_eol
  1085. clear_to_eol:
  1086. ;enter with dl=current row, dh=current column.
  1087.     push    bx
  1088.     mov    bl,num_screen_cols
  1089.     call    clear_count
  1090.     pop    bx
  1091.     ret
  1092.  
  1093.  
  1094.     public    clear_count
  1095. clear_count:
  1096. ;enter with dl=current row, dh=current column, bl=column to clear to.
  1097.     push    ax
  1098.     push    bx
  1099.     push    cx
  1100.     push    si
  1101.     push    di
  1102.     push    bp
  1103.     push    es
  1104. clear_count_0:
  1105.     cmp    dh,bl        ;already past it?
  1106.     jae    clear_count_3    ;yes.
  1107.  
  1108.     mov    ah,color
  1109.     mov    al,' '            ;clear to the background color.
  1110.     push    ax
  1111.     call    get_video_ptr
  1112.     assume    ds:nothing, es:nothing
  1113.  
  1114.     mov    cl,bl            ;compute the number of chars to clear.
  1115.     sub    cl,dh
  1116.     mov    ch,0
  1117.  
  1118.     pop    ax
  1119.  
  1120.     cmp    ibm_cga,0        ;slow refresh?
  1121.     je    clear_count_2
  1122.  
  1123.     push    dx
  1124.     mov    bx,ax            ;retrace_wait destroys ax.
  1125.     mov    dx,crt_status        ;load it only once.
  1126. clear_count_1:
  1127.     retrace_wait
  1128.     mov    ax,bx
  1129.     stosw
  1130.     loop    clear_count_1
  1131.     pop    dx
  1132.     jmp    short clear_count_3
  1133.  
  1134. clear_count_2:
  1135.     rep    stosw
  1136.  
  1137. clear_count_3:
  1138.     pop    es
  1139.     assume    ds:nothing, es:data
  1140.     pop    bp
  1141.     pop    di
  1142.     pop    si
  1143.     pop    cx
  1144.     pop    bx
  1145.     pop    ax
  1146.     ret
  1147.  
  1148.  
  1149. get_video_ptr:
  1150. ;enter with dl=current row, dh=current column.
  1151. ;doesn't destroy bx.
  1152. ;return with es:di->character position.
  1153.     mov    al,screen_columns    ;compute the offset of the char.
  1154.     mul    dl
  1155.     add    al,dh
  1156.     adc    ah,0
  1157.     shl    ax,1
  1158.     mov    di,ax
  1159. get_video_seg:
  1160. ;return with es,ax=video segment.
  1161.     xor    ax,ax
  1162.     mov    es,ax
  1163.     mov    ax,0b000h
  1164.     cmp    byte ptr es:[449h],7    ;MDA?
  1165.     je    get_video_seg_1        ;yes - we have the segment already.
  1166.     mov    ax,0b800h        ;no - segment at b800h.
  1167. get_video_seg_1:
  1168.     mov    es,ax
  1169.     mov    ah,0feh            ;let desqview change the segment.
  1170.     int    10h
  1171.     mov    ax,es
  1172.     ret
  1173.  
  1174.  
  1175.     public    xychrout
  1176. xychrout:
  1177. ;enter with dh=col, dl=row, al=character to print, ah=font to print it in.
  1178.     push    ax            ;save everything that we might need.
  1179.     push    bx
  1180.     push    cx
  1181.     push    dx
  1182.     push    di
  1183.     push    si
  1184.     push    es
  1185.     push    ds
  1186.     mov    bx,es
  1187.     mov    ds,bx
  1188.     cmp    dh,screen_columns    ;past the right margin?
  1189.     jae    xychrout_3        ;yes - don't print.
  1190.     cmp    ah,0            ;font zero?
  1191.     jne    xychrout_5        ;no - print specially.
  1192.     mov    ah,color        ;assume no inverse video
  1193.     cmp    al,0ffh            ;print 255 specially
  1194.     je    xychrout_del
  1195.     cmp    al,20h            ;is this a space or so?
  1196.     jb    xychrout_control    ;print control chars specially.
  1197.     jmp    short xychrout_1
  1198. xychrout_del:
  1199.     mov    al,7fh-'@'        ;show bold del.
  1200. xychrout_control:
  1201.     mov    ah,control_color
  1202.     add    al,'@'
  1203.     jmp    short xychrout_1
  1204. xychrout_5:
  1205.     mov    ah,whitespc_color
  1206.     mov    bx,offset font_8_table
  1207.     sub    al,4dh            ;first character in font 8.
  1208.     xlat
  1209. xychrout_1:
  1210.     cmp    inversing,0    ; check    inversion flag
  1211.     je    no_invers    ; skip inversion code
  1212.     mov    cl,4        ; we're    inversing: so exchange
  1213.     rol    ah,cl        ; fore & background color
  1214.     and    ah,7Fh        ; avoid    blinking background
  1215. no_invers:
  1216.     mov    bx,ax            ;save the char in bx.
  1217.     call    get_video_ptr
  1218.     assume    ds:nothing, es:nothing
  1219.     cmp    ibm_cga,0        ;if we have an IBM CGA, we have to wait
  1220.     je    xychrout_4        ;  for retrace, otherwise not.
  1221.     mov    dx,crt_status
  1222.     retrace_wait
  1223. xychrout_4:
  1224.     mov    ax,bx
  1225.     stosw
  1226. xychrout_3:
  1227.     pop    ds
  1228.     pop    es
  1229.     assume    ds:nothing, es:data
  1230.     pop    si
  1231.     pop    di
  1232.     pop    dx
  1233.     pop    cx
  1234.     pop    bx
  1235.     pop    ax
  1236.     ret
  1237.  
  1238.  
  1239.     public    hardware_roll_down
  1240. hardware_roll_down:
  1241. ;exit: if this machine is capable of hardware roll, do it and exit with cy=0,
  1242. ;  otherwise, exit with cy=1.  The hardware roll must leave the last line
  1243. ;  on the screen as the last line.
  1244. ;preserve bx.
  1245.     cmp    ibm_cga,0
  1246.     je    no_roll_down
  1247.  
  1248.     push    bx
  1249.     push    cx
  1250.     push    dx
  1251.     mov    ch,ah
  1252.     mov    cl,0
  1253.     mov    dh,al
  1254.     mov    dl,num_screen_cols
  1255.     dec    dl
  1256.     mov    bh,color
  1257.     mov    ax,701h
  1258.     int    10h
  1259.     pop    dx
  1260.     pop    cx
  1261.     pop    bx
  1262.     clc
  1263.     ret
  1264. no_roll_down:
  1265.     stc
  1266.     ret
  1267.  
  1268.  
  1269.     public    hardware_roll_up
  1270. hardware_roll_up:
  1271. ;exit: if this machine is capable of hardware roll, do it and exit with cy=0,
  1272. ;  otherwise, exit with cy=1.  The hardware roll must leave the last line
  1273. ;  on the screen as the last line.
  1274. ;preserve bx.
  1275.     cmp    ibm_cga,0
  1276.     je    no_roll_up
  1277.  
  1278.     push    bx
  1279.     push    cx
  1280.     push    dx
  1281.     mov    ch,ah
  1282.     mov    cl,0
  1283.     mov    dh,al
  1284.     mov    dl,num_screen_cols
  1285.     dec    dl
  1286.     mov    bh,color
  1287.     mov    ax,601h
  1288.     int    10h
  1289.     pop    dx
  1290.     pop    cx
  1291.     pop    bx
  1292.     clc
  1293.     ret
  1294. no_roll_up:
  1295.     stc
  1296.     ret
  1297.  
  1298.  
  1299.     public    set_screen_color
  1300. set_screen_color:
  1301. ;enter with si -> list of colors (fore, back, control, whitespc)
  1302.     mov    cl,4
  1303.     mov    ah,[si+1]        ;background doesn't change.
  1304.     shl    ah,cl
  1305.     and    ah,70h            ;don't let them set blinking colors.
  1306.     mov    al,[si]            ;compute the normal attributes.
  1307.     or    al,ah
  1308.     mov    color,al
  1309.     mov    al,[si+2]        ;now the control attributes.
  1310.     or    al,ah
  1311.     mov    control_color,al
  1312.     mov    al,[si+3]        ;now the whitespace attributes.
  1313.     or    al,ah
  1314.     mov    whitespc_color,al
  1315.     ret
  1316.  
  1317.  
  1318.     public    pick_init, pick_on, pick_off, check_pick, get_pick_values
  1319. pick_init:
  1320.     call    mouse_exists
  1321.     mov    ax,0
  1322.     int    33h
  1323.     mov    mouse_flag,al        ;remember if the mouse exists.
  1324.     mov    mouse_buttons,bl    ;remember the number of buttons.
  1325.     mov    ax,4            ;move the mouse to the upper right hand.
  1326.     mov    cx,635
  1327.     mov    dx,0
  1328.     int    33h
  1329.     mov    ax,10            ;set text cursor (ignored on Z-100).
  1330.     mov    bx,0            ;software text cursor.
  1331.     mov    cx,77ffh        ;screen mask
  1332.     mov    dx,7700h        ;cursor mask
  1333.     int    33h
  1334.  
  1335.     mov    al,max_screen_line    ;compute the "number of scan lines"
  1336.     add    al,2
  1337.     mul    scan_lines_per_char
  1338.     dec    dx
  1339.     mov    dx,ax            ;set the "number of scan lines"
  1340.     mov    cx,0
  1341.     mov    ax,8
  1342.     int    33h
  1343.  
  1344.     mov    al,8            ;we're assuming nine bits per char.
  1345.     mul    screen_columns
  1346.     dec    ax
  1347.     mov    dx,ax            ;set the "number of bit columns"
  1348.     mov    cx,0
  1349.     mov    ax,7
  1350.     int    33h
  1351.  
  1352.     call    check_pick        ;ensure that there are no up or down
  1353.     call    check_pick        ;  events left.
  1354.     call    check_pick
  1355.     call    check_pick
  1356.     call    check_pick
  1357.     call    check_pick
  1358.     ret
  1359.  
  1360.  
  1361. pick_on:
  1362.     call    mouse_exists
  1363.     mov    ax,1
  1364.     int    33h
  1365.     ret
  1366.  
  1367.  
  1368. pick_off:
  1369.     call    mouse_exists
  1370.     mov    ax,1            ;ensure that we work with MOUSEKEY.
  1371.     int    33h
  1372.     mov    ax,2
  1373.     int    33h
  1374.     ret
  1375.  
  1376.  
  1377. check_pick:
  1378. ;return nz and al=pick character.  return zr if no pick.
  1379.     call    mouse_exists
  1380.     push    bx
  1381.     push    cx
  1382.     push    dx
  1383.     cmp    mouse_flag,0        ;inhibit mouse presses if it isn't there.
  1384.     je    check_pick_1
  1385.     mov    ax,5
  1386.     mov    bx,0            ;left button press
  1387.     int    33h
  1388.     mov    ax,0feh
  1389.     or    bx,bx
  1390.     jne    check_pick_1
  1391.     mov    ax,5            ;right button press
  1392.     mov    bx,1
  1393.     int    33h
  1394.     mov    ax,0fdh
  1395.     or    bx,bx
  1396.     jne    check_pick_1
  1397.     mov    ax,6            ;left button release
  1398.     mov    bx,0
  1399.     int    33h
  1400.     mov    ax,0fch
  1401.     or    bx,bx
  1402.     jne    check_pick_1
  1403.     mov    ax,6            ;right button release
  1404.     mov    bx,1
  1405.     int    33h
  1406.     mov    ax,0fbh
  1407.     or    bx,bx
  1408.     jne    check_pick_1
  1409.     cmp    mouse_buttons,2        ;do we have only two buttons?
  1410.     je    check_pick_1        ;yes - no pick.
  1411.     mov    ax,6            ;middle button release
  1412.     mov    bx,2
  1413.     int    33h
  1414.     mov    ax,0f9h
  1415.     or    bx,bx
  1416.     jne    check_pick_1
  1417.     mov    ax,5            ;middle button press
  1418.     mov    bx,2
  1419.     int    33h
  1420.     mov    ax,0fah
  1421.     or    bx,bx
  1422.     jne    check_pick_1
  1423. check_pick_1:
  1424.     pop    dx
  1425.     pop    cx
  1426.     pop    bx
  1427.     ret
  1428.  
  1429. get_pick_values:
  1430.     mov    cx,0
  1431.     mov    dx,0
  1432.     call    mouse_exists
  1433.     mov    ax,3
  1434.     int    33h
  1435.  
  1436.     push    cx            ;save the x value.
  1437.  
  1438.     mov    ax,dx
  1439.     div    scan_lines_per_char
  1440.     mov    ah,0
  1441.     push    ax
  1442.     call    read_linesbefore
  1443.     push    ax
  1444.     call    read_newrow
  1445.     pop    bx
  1446.     sub    bx,ax            ;bx=linesbefore - newrow.
  1447.     pop    dx
  1448.     add    dx,bx            ;add y-value.
  1449.     inc    dx            ;ax= y-value - newrow + linesbefore + 1.
  1450.     pop    ax            ;compute the x-value.
  1451.  
  1452.     push    dx
  1453.  
  1454.     mov    cl,8
  1455.     div    cl
  1456.     mov    ah,0
  1457.     inc    ax
  1458.     push    ax            ;add in firstcolumn.
  1459.     call    read_firstcolumn
  1460.     pop    cx
  1461.     add    cx,ax
  1462.  
  1463.     pop    dx
  1464.  
  1465.     ret
  1466.  
  1467.     extrn    read_firstcolumn: near
  1468.     extrn    read_linesbefore: near
  1469.     extrn    read_newrow: near
  1470.  
  1471.  
  1472. ;this routine returns from the routine that called it if the mouse is not
  1473. ;  installed.
  1474. mouse_exists:
  1475.     push    ds
  1476.     xor    ax,ax
  1477.     mov    ds,ax
  1478.     mov    ax,word ptr ds:[33h*4+2]
  1479.     pop    ds
  1480.     cmp    ax,0            ;any mouse interrupt at all?
  1481.     je    mouse_exists_2        ;no - no mouse.
  1482.     cmp    ax,40h            ;is the mouse interrupt in the bios?
  1483.     jne    mouse_exists_1        ;no - must be a real mouse.
  1484. mouse_exists_2:
  1485.     add    sp,2
  1486.     xor    ax,ax
  1487.     ret
  1488. mouse_exists_1:
  1489.     ret
  1490.  
  1491. code    ends
  1492.  
  1493.     end
  1494.